package com.xiyuan.smartutils.template.engine.statement;

import com.xiyuan.smartutils.StrUtils;
import com.xiyuan.smartutils.Validates;
import com.xiyuan.smartutils.template.engine.StatementParser;
import com.xiyuan.smartutils.template.engine.TagType;
import com.xiyuan.smartutils.template.engine.Template;
import com.xiyuan.smartutils.template.engine.VariableMap;
import com.xiyuan.smartutils.template.engine.exception.StatementException;

import java.io.PrintWriter;

@SuppressWarnings("AlibabaLowerCamelCaseVariableNaming")
public class _INCLUDE extends Statement {
    private static final long serialVersionUID = 1L;
    private Template view;
    
    public _INCLUDE(StatementParser parser) {
        super(parser);
    }
    
    @Override
    protected void build(VariableMap variableMap, PrintWriter out) {
        if (expressions.isEmpty()) {return;}
        
        Object obj = expressions.get(0).execute(variableMap);
        if (obj == null) {return;}
        
        try {
            String resourcePath = obj.toString();
            view = Template.parseFile(resourcePath);
            if (view.getError() != null) {throw view.getError();}
            
            view.execute(variableMap, out);
        }
        catch (Throwable e) {
            throw new StatementException(getPath(), getLineNo(), getBeginColumn(), this.toString(), e);
        }
    }
    
    @Override
    public TagType getType() {
        return TagType.INCLUDE;
    }
    
    @Override
    public boolean parseTag(StatementParser parser) throws StatementException {
        StringBuilder value = new StringBuilder();
        String variableName = null;
        
        int expression_begin_line = this.getLineNo(), expression_begin_column = this.getBeginColumn();
        // 等号发现的行数,以及位置
        int equal_line = expression_begin_line, equal_column = 0;
        char ch = 0, quote = 0, prvChar = 0;
        boolean space = false;
        while (parser.hasNext()) {
            prvChar = value.length() == 0 ? 0 : ch;
            ch = parser.next();
            if (value.length() == 0 && Validates.isWhitespace(ch)) {
                space = true;
                continue;
            }
            
            value.append(ch);
            if (!space) {
                // 只是以#include开头而已
                return false;
            }
            
            if (value.length() == 1) {
                expression_begin_line = parser.getLineNum();
                expression_begin_column = parser.getColumn();
            }
            
            if (variableName == null) {
                // 未找到变量名时
                
                if ('=' == ch) {
                    // 找到变量名
                    if (value.length() == 1) {
                        String path = this.getPath(), msg = StrUtils.formats("%s属性src未定义", getType());
                        throw new StatementException(path, expression_begin_line, expression_begin_column, msg);
                    }
                    
                    variableName = StrUtils.trim(value.substring(0, value.length() - 1));
                    if (!"src".equals(variableName)) {
                        String fmt = "%s标签解析时未找到src属性。当前值【%s】";
                        String path = this.getPath(), msg = StrUtils.formats(fmt, getType(), variableName);
                        throw new StatementException(path, expression_begin_line, expression_begin_column, msg);
                    }
                    
                    equal_line = parser.getLineNum();
                    equal_column = parser.getColumn();
                    value.setLength(0);
                    continue;
                }
                
                // 判断标签是否结束 ,当前标签为‘>’视为结束
                int endTagIndex = ch == _GATHER_ ? value.length() - 1 : -1;
                if (endTagIndex > 0 && value.charAt(endTagIndex - 1) == _SLASH_) {
                    endTagIndex--;// 如果是 ‘/>’ 结束则需要重置 结束索引 为‘/’对应的索引
                }
                else {
                    endTagIndex = -1;
                    // 否则为完成
                }
                
                if (endTagIndex != -1) {
                    String val = StrUtils.trim(value.substring(0, endTagIndex));
                    StringBuffer err = new StringBuffer(getType() + "标签解析结束，");
                    if (val.isEmpty()) {err.append("但未找到src属性！");}
                    else if (!"src".equals(val)) {err.append("但未找到src属性。当前值【").append(val).append("】");}
                    else {err.append("%s标签解析结束，src属性尚未初始化");}
                    
                    String path = this.getPath();
                    throw new StatementException(path, expression_begin_line, expression_begin_column, err.toString());
                }
                
                continue;
            }
            
            // 解析数据值
            if (quote == 0 && (ch == _DOUBLE_QUOTE_ || ch == _QUOTE_)) {
                // 记录 字符串开始
                quote = ch;
                continue;
            }
            
            // 字符串结束
            if (quote != 0 && prvChar != _BACK_SLASH_ && ch == quote) {
                quote = 0;
                continue;
            }
            
            // 判断标签是否结束 ,当前标签为‘>’视为结束
            int endTagIndex = ch == _GATHER_ ? value.length() - 1 : -1;
            if (endTagIndex > 0 && value.charAt(endTagIndex - 1) == _SLASH_) {
                endTagIndex--;// 如果是 ‘/>’ 结束则需要重置 结束索引 为‘/’对应的索引
            }
            
            if (quote == 0 && endTagIndex != -1) {
                
                
                if (endTagIndex == 0) {
                    String fmt = "%s标签变量【%s】]未初始化或者未赋予表达式";
                    String path = this.getPath(), msg = StrUtils.format(fmt, getType(), variableName);
                    throw new StatementException(path, equal_line, equal_column, msg);
                }
                
                
                // 标记标签就绪
                this.setCompleteTag();
                
                // 解析表达式
                value.setLength(endTagIndex);
                this.parseExpression(expression_begin_line, expression_begin_column, value);
                break;
            }
        }
        
        if (variableName == null) {
            String fmt = "文档已结束。%s标签未找到赋值符‘=’";
            String path = this.getPath(), msg = StrUtils.format(fmt, getType());
            throw new StatementException(path, this.getLineNo(), this.getBeginColumn(), msg);
        }
        
        if (!this.isCompleteTag()) {
            String fmt = "文档已结束。%s标签未找到结束符‘/>’";
            String path = this.getPath(), msg = StrUtils.format(fmt, getType());
            throw new StatementException(path, this.getLineNo(), this.getBeginColumn(), msg);
        }
        
        String stmt = (expressions.isEmpty() ? "" : (" " + expressions.get(0))) + getType().getTagComplete();
        this.setStatement(this.getStatement() + stmt);
        return true;
    }
    
}
